require('./VirtualNode');
var Bind = require('./Bind');
var RUNTIME_NAMES = require('./StringEscape').RUNTIME_NAMES;
var expParser = require('./expParser');
var o = RUNTIME_NAMES.TOP_SCOPE + ',' + RUNTIME_NAMES.SUB_SCOPE + ',' + RUNTIME_NAMES.CALLER;
module.exports = {
    requireBlock: true,
    addDefaultAttrs: [
        {
            n: 'wx:for-index',
            v: 'index'
        },
        {
            n: 'wx:for-item',
            v: 'item'
        }
    ],
    precompile: function (e, t, i) {
        var n = t.match(/^\{\{(.+)\}\}$/);
        if (!n)
            throw new Error('Illegal expression is found in wx:for.');
        var a = expParser.parse(n[1]);
        var s = expParser.lvalueStringify(a, i);
        var l = expParser.searchBindingPaths([a], i);
        return {
            s: [],
            d: 'function(' + o + '){return ' + expParser.stringify(a, i) + '}',
            l: s,
            b: l
        };
    },
    register: function (e, t, i) {
    },
    create: function (e, t, i, a, r, o, s, l, d, A) {
        var c = i._wxForIndex || 'index';
        var h = i._wxForItem || 'item';
        var u = i._wxKey;
        var p = d.createVirtualNode('wx:for:list');
        i.id && (p.id = i.id);
        Bind.create('', o, s, function (e, i, n) {
            var a = t.d(e, i, null);
            w(a, e, i, n);
            return a;
        }, t.l, t.b);
        var g = function (e, t, a, r, u) {
            var g = d.createVirtualNode('wx:for:item');
            var _ = Bind.proxyTopScope(o);
            var f = Bind.proxySubScopes(s);
            g.__wxTopScope = _;
            g.__wxSubScopes = f;
            g.__wxForToRemove = false;
            g.__wxForKeyStr = '';
            var v = Bind.create(c, _, f, null, null, []);
            var w = Bind.create(h, _, f, null, [a], []);
            f[c] = v;
            f[h] = w;
            t[c] = a;
            t[h] = r;
            A(i.c, d, g, e, t, _, f, l);
            undefined === u ? p.appendChild(g) : p.insertBefore(g, u);
            return g;
        };
        var _ = function (e, t, i, r, o, s) {
            var l = e.__wxSubScopes[h];
            Bind.updateLvaluePath(l, [r]);
            o && (s ? p.insertBefore(e, s) : p.appendChild(e));
            var d = e.__wxSubScopes[c];
            i[c] = r;
            Bind.updateBinding(d, [], a, i, t);
        };
        var f = function (e, t, i, a, r, o) {
            a[h] = r;
            Bind.updateBinding(e.__wxSubScopes[h], t, i, a, o);
        };
        var v = function (e) {
            for (var t in (Bind.removeBindingsForScope(e.__wxTopScope), p.__wxSubScopes))
                Bind.removeBindingsForScope(e.__wxSubScopes[t]);
            p.removeChild(e);
        };
        var w = function (e, t, i, n) {
            var a = '';
            var r = e;
            'object' == typeof e && null !== e || (r = []);
            var o = {};
            for (a in i)
                o[a] = i[a];
            var s = 0;
            if (u) {
                var l = [];
                var d = e instanceof Array;
                var A = [];
                if (!d) {
                    var c = r;
                    for (a in (r = [], c))
                        r.push(c[a]), A.push(a);
                }
                for (s = 0; s < r.length; s++)
                    l.push(String(r[s][u]));
                if (0 === r.length)
                    for (; p.childNodes.length;)
                        v(p.childNodes[0]);
                else {
                    var h = Object.create(null);
                    var w = Object.create(null);
                    var m = p.childNodes;
                    var I = null;
                    var b = '';
                    for (s = 0; s < m.length; s++)
                        h[b = (I = m[s]).__wxForKeyStr] >= 0 ? (v(I), s--) : (h[b] = s, w[b] = I, I.__wxForToRemove = true);
                    var C = -1;
                    var y = 0;
                    var E = 1;
                    var x = [];
                    (y = h[r[0][u]]) >= 0 || (y = -1);
                    m[y] && (m[y].__wxForToRemove = false);
                    for (s = 1; s < r.length; s++)
                        (E = h[r[s][u]]) >= 0 && (C < y && (y < E || C > E) && (x.push(m[y]), C = y), m[y = E] && (m[y].__wxForToRemove = false));
                    C < y && x.push(m[y]);
                    for (s = 0; s < m.length; s++)
                        (I = m[s]).__wxForToRemove && (v(I), s--);
                    var B = x.shift();
                    var S = 0;
                    for (s = 0; s < r.length; s++) {
                        var Q = r[s];
                        var k = w[Q[u]];
                        w[Q[u]] = null;
                        if (k) {
                            var D = true;
                            if (k === B) {
                                for (; m[S] !== B;)
                                    S++;
                                S++;
                                B = x.shift();
                                D = false;
                            }
                            _(I = k, n, o, d ? s : A[s], D, m[S]);
                            D && m[S] === I && S++;
                            f(I, [], t, o, r[s], n);
                        } else
                            I = g(t, o, d ? s : A[s], r[s], m[S]), S++, I.__wxForKeyStr = String(Q[u]);
                    }
                }
            } else {
                for (; p.childNodes.length;)
                    v(p.childNodes[0]);
                if (e instanceof Array)
                    for (s = 0; s < r.length; s++)
                        g(t, o, s, r[s]);
                else
                    for (a in r)
                        g(t, o, a, r[a]);
            }
        };
        w(t.d(a, r, null), a, r, null);
        return p;
    }
};
